<template>
  <transition name="fade">
    <div class="im" v-show="isShow">
      <div class="mask" @click="hide"></div>
      <Lemon-imui
        ref="IMUI"
        class="imui"
        width="1000px"
        height="660px"
        avatarCricle
        :user="user"
        @send="handleSend"
        @pull-messages="handlePullMessages"
        @change-contact="handleChangeContact"
        @message-click="handleMsgClick">
        <template slot="message-title" slot-scope="scope">
          <div class="msg-title">
            <div class="msg-title__left">
              <h2>{{ scope.displayName }}</h2>
            </div>
            <div class="msg-title__right">
              <img src="../../../static/img/im/close.png" title="关闭" @click="hide" />
            </div>
          </div>
        </template>
      </Lemon-imui>
    </div>
  </transition>
</template>

<script>
  import { mapState } from 'vuex'
  import { LIVESOCKET, SERVERTAPI } from '@/config'
  import pinyin4js from 'pinyin4js'
  import axios from "@/api/config"
  import emoji from './emoji'
  import WebsocketHeartbeatJs from 'websocket-heartbeat-js'

  export default {
    name: 'IM',

    data () {
      return {
        isShow: false,
        ws: null,
        current: 1,
        isPreview: false,
        currentUserid: '',
        imgList: [],
        emojiList: emoji.emojiList,
        msgSound: `${SERVERTAPI}/static/message/message.mp3`,
        audio: null
      }
    },
    
    computed: {
      ...mapState(['userInfo', 'token']),

      user () {
        return {
          id: this.token,
          avatar: this.userInfo.headimgurl,
          displayName: this.userInfo.user_name
        }
      }
    },

    watch: {
      token: {
        handler (v) {
          if (v) {
            this.initIM()
          } else {
            this.ws && this.ws.close()
          }
        },
        deep: true,
        immediate: true
      }
    },

    mounted () {
      this.audio = new Audio(this.msgSound)
    },

    methods: {
      show (user) {
        if (!user.userId) {
          document.querySelector('body').style.overflow = 'hidden'
          this.isShow = true

          return false
        }

        const contacts = this.$refs.IMUI.getContacts()

        if (!contacts.map(v => v.id).includes(user.userId)) {
          setTimeout(() => {
            this.$refs.IMUI.initContacts([
              {
                id: user.userId,
                displayName: user.userName,
                avatar: user.userAvatar,
                index: pinyin4js.convertToPinyinString(user.userName.substr(0, 1), '', pinyin4js.FIRST_LETTER).toLocaleUpperCase(),
                unread: 0,
                lastContent: this.$refs.IMUI.lastContentRender({ type: 'text', content: ' ' }),
                lastSendTime: new Date().getTime()
              },
              ...contacts
            ])

            this.$nextTick(() => {
              this.$refs.IMUI.changeContact(user.userId)
              document.querySelector('body').style.overflow = 'hidden'
              this.isShow = true
            })
          }, 300)
        }

        this.$nextTick(() => {
          this.$refs.IMUI.changeContact(user.userId)
          document.querySelector('body').style.overflow = 'hidden'
          this.isShow = true
        })
      },

      initIM () {
        this.ws = new WebsocketHeartbeatJs({
          url: LIVESOCKET,
          pingTimeout: 15000,
          pongTimeout: 10000,
          reconnectTimeout: 3000,
          pingMsg: JSON.stringify({
            type: 'ping',
            id: this.token
          })
        })

        this.ws.onopen = () => {
          console.log('连接成功!')
          this.$refs.IMUI.initEditorTools([{
            name:'emoji'
          }, {
            name:'uploadImage'
          }])

          this.$refs.IMUI.initEmoji(this.emojiList)
        }

        this.ws.onmessage = e => {
          const data = JSON.parse(e.data)

          console.log(data)
          if (data.type === 'init') {
            const client_id = data.data.client_id

            if (this.token) {
              this.ws.send(JSON.stringify({
                type: 'bind_id',
                id: this.token,
                client_id
              }))
            }

            return false
          }

          if (data.type === 'imcountnum') {
            this.$store.commit('SET_MSG_COUNT', data.data.imcountnum)
          }

          if (data.type === 'say') {
            const msg = {
              id: new Date().getTime(),
              status: 'succeed',
              type: data.data.message_type === 'img' ? 'image' : data.data.message_type,
              sendTime: new Date().getTime(),
              content: this.formatMsg(data.data.message, data.data.message_type),
              toContactId: data.data.fromid,
              fromUser: {
                id: data.data.fromid,
                displayName: data.data.from_username,
                avatar: data.data.from_headimgurl
              }
            }
            this.$refs.IMUI.appendMessage(msg, true)
            
            if (this.$refs.IMUI.getCurrentContact().id === data.data.fromid) {
              this.ws.send(JSON.stringify({
                type: 'readmsg',
                data: {
                  fromid: this.token,
                  toid: data.data.fromid
                }
              }))
            }

            this.ws.send(JSON.stringify({
              type: 'imcountnum',
              id: this.token
            }))

            this.audio.play()
          }

          if (data.type === 'readmsg') {
            this.ws.send(JSON.stringify({
              type: 'chatlist',
              data: {
                fromid: this.token
              }
            }))

            this.ws.send(JSON.stringify({
              type: 'imcountnum',
              id: this.token
            }))
          }

          if (data.type === 'chatlist') {
            this.initContacts(data.data)

            return false
          }

          if (data.type === 'bind_id') {
            this.ws.send(JSON.stringify({
              type: 'chatlist',
              data: {
                fromid: this.token
              }
            }))

            this.ws.send(JSON.stringify({
              type: 'imcountnum',
              id: this.token
            }))
          }
        }

        this.ws.onreconnect = function () {
          console.log('重连中')
        }

        this.ws.onclose = () => {
          console.log('关闭成功!')
        }
      },

      handleMsgClick (e, key, msg) {
        if (msg.type === 'image') {
          // this.$viewerApi({
          //   images: [msg.content]
          // })
          this.$hevueImgPreview(msg.content)
        }
      },

      handleChangeContact (contact) {
        let i = 0
        this.ws.send(JSON.stringify({
          type: 'readmsg',
          data: {
            fromid: this.token,
            toid: contact.id
          }
        }))
        
        setTimeout(() => {
          document.querySelectorAll('.lemon-message__content img').forEach((v, index) => {
            const src = v.getAttribute('src')
            v.onload = () => {
              i = i + 1

              if (i === document.querySelectorAll('.lemon-message__content img').length) {
                document.querySelector('.lemon-messages').scrollTo(0, 100000)
              }
            }

            document.querySelector('.lemon-messages').scrollTo(0, 100000)
          })
        }, 200)

        document.querySelector('.lemon-messages').scrollTo(0, 100000)
      },

      formatMsg (content, msgType) {
        if (content.indexOf('img[') === 0 && msgType === 'img') {
          return content.substring(4, content.length - 1)
        }

        if (msgType === 'text' && /face\[(.+)\]/.test(content)) {
          return this.mapEmojiValue(content)
        }

        return content
      },

      handlePullMessages(contact, next) {
        if (contact.id !== this.currentUserid) {
          this.current = 1
        }

        this.currentUserid = contact.id

        this.$http.getChartMsgList({
          shop_token: contact.id,
          page: this.current
        }).then(res => {
          if (res.status === 200) {
            if (!res.data.length) return next([], true)

            const list = res.data.map(v => {
              return {
                id: v.id,
                status: 'succeed',
                type: v.messagetype === 'img' ? 'image' : v.messagetype,
                sendTime: v.createtime * 1000,
                content: this.formatMsg(v.message, v.messagetype),
                toContactId: contact.id,
                fromUser: {
                  id: v.fromid,
                  displayName: v.from_user.user_name,
                  avatar: v.from_user.avatar
                }
              }
            }).reverse()

            if (list.length === 10) {
              this.current = this.current + 1
            }

            next(list, list.length < 10 ? true : false)
          }
        })
      },

      mapEmojiValue (str) {
        let value = ''
        let obj = {}
        if (!/face\[([\u4e00-\u9fa5]+)\]/g) {
          return str
        }
        let len = str.match(/face\[([\u4e00-\u9fa5]+)\]/g).length
        str.match(/face\[([\u4e00-\u9fa5]+)\]/g).forEach((v, index) => {
          if (this.emojiList.filter(e => e.value === v).length) {
            const emojiName = `[!${this.emojiList.filter(e => e.value === v)[0].name}]`
            if (obj[index - 1]) {
              if (len - 1 === index) {
                value = obj[index - 1].replace(v, emojiName)
              } else {
                obj[index] = obj[index - 1].replace(v, emojiName)
              }
            } else {
              if (len === 1) {
                value = str.replace(v, emojiName)
              } else {
                obj[index] = str.replace(v, emojiName)
              }
            }
          }
        })

        return value || str
      },

      getEmojiValue (str) {
        let value = ''
        let obj = {}
        if (!str.match(/\[!(\w+)\]/g)) {
          return str
        }
        let len = str.match(/\[!(\w+)\]/g).length
        str.match(/\[!(\w+)\]/g).forEach((v, index) => {
          if (this.emojiList.filter(e => e.name === v.match(/\[!(\w+)\]/)[1]).length) {
            if (obj[index - 1]) {
              if (len - 1 === index) {
                value = obj[index - 1].replace(v, this.emojiList.filter(e => e.name === v.match(/\[!(\w+)\]/)[1])[0].value)
              } else {
                obj[index] = obj[index - 1].replace(v, this.emojiList.filter(e => e.name === v.match(/\[!(\w+)\]/)[1])[0].value)
              }
            } else {
              if (len === 1) {
                value = str.replace(v, this.emojiList.filter(e => e.name === v.match(/\[!(\w+)\]/)[1])[0].value)
              } else {
                obj[index] = str.replace(v, this.emojiList.filter(e => e.name === v.match(/\[!(\w+)\]/)[1])[0].value)
              }
            }
          }
        })

        return value || str
      },

      handleSend (e, next, file) {
        if (e.type === 'text' && /\[!(\w+)\]/.test(e.content)) {
          this.ws.send(JSON.stringify({
            type: 'say',
            data: {
              fromid: this.token,
              toid: e.toContactId,
              message: this.getEmojiValue(e.content),
              message_type: e.type
            }
          }))

          next()
          return false
        }

        if (e.type === 'image') {
          this.upload(file).then(res => {
            if (res.status === 200) {
              this.ws.send(JSON.stringify({
                type: 'say',
                data: {
                  fromid: this.token,
                  toid: e.toContactId,
                  message: `img[${res.data.full_path}]`,
                  message_type: 'img'
                }
              }))
            }
          })
          next()
          return false
        }

        this.ws.send(JSON.stringify({
          type: 'say',
          data: {
            fromid: this.token,
            toid: e.toContactId,
            message: e.content,
            message_type: e.type
          }
        }))
        next()
      },

      upload (file) {
        const params = this.$http.returnCommonParams('api/Common/uploadPic', 'chart')
        let formData = new FormData()

        Object.keys(params).forEach(v => {
          formData.append(v, params[v])
        })
        formData.append('file', file)

        return axios.post(`api/Common/uploadPic`, formData, {
          headers: {
            'Content-Type': 'multipart/form-data'
          }
        })
      },

      mapMsgType (e) {
        if (e.message_type === 'img') {
          return '[图片]'
        }

        if (e.message_type === 'goods') {
          return '[商品]'
        }

        return e.message
      },

      initContacts (e) {
        const list = e.map(v => {
          const name = v.fromid === this.token ? v.to_username : v.from_username
          return {
            id: v.fromid === this.token ? v.toid : v.fromid,
            displayName: name,
            avatar: v.fromid === this.token ? v.to_headimgurl : v.from_headimgurl,
            index: pinyin4js.convertToPinyinString(name.substr(0, 1), '', pinyin4js.FIRST_LETTER).toLocaleUpperCase(),
            unread: v.msgcount,
            lastContent: this.$refs.IMUI.lastContentRender({ type: 'text', content: this.mapMsgType(v) }),
            lastSendTime: v.createtime * 1000
          }
        })

        this.$refs.IMUI.initContacts(list)
      },

      hide () {
        document.querySelector('body').style.overflow = 'auto'
        this.isShow = false
      }
    }
  }
</script>

<style lang="scss" scoped>
  .im {
    position: fixed;
    left: 0;
    top: 0;
    z-index: 1111;
    width: 100%;
    height: 100%;

    .imui {
      position: absolute;
      top: 50%;
      left: 50%;
      z-index: 111;
      transform: translate(-50%, -50%);

      .msg-title {
        display: flex;
        align-items: center;
        justify-content: space-between;

        .msg-title__right {
          display: flex;
          align-items: center;

          img {
            width: 20px;
            cursor: pointer;
            transition: all ease 0.5s;

            &:hover {
              opacity: 0.6;
            }
          }
        }
      }
    }

    /deep/ .imui {
      .lemon-messages {
        padding: 0 15px!important;
      }

      .lemon-message {
        margin: 10px 0;
        padding: 0!important;
      }

      .lemon-message__title {
        margin-bottom: 8px;
      }

      .lemon-editor__emoji-item {
        width: 28px;
      }

      .lemon-container__title {
        border-bottom: 1px solid #e9e9e9;
      }

      .lemon-editor {
        border-top: 1px solid #e9e9e9;
      }


      .lemon-message-text .lemon-message__content img {
        width: auto;
      }

      .lemon-message-image .lemon-message__content img {
        max-width: 200px!important;
        min-width: auto!important;
        width: auto;
        height: auto!important;
      }
    }

    .mask {
      position: absolute;
      left: 0;
      top: 0;
      z-index: 1;
      width: 100%;
      height: 100%;
      background: rgba(0, 0, 0, 0.8);
    }
  }
</style>
